package config

import (
	"fmt"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

// ConfigManager 配置管理器
type ConfigManager struct {
	config     *Config
	viper      *viper.Viper
	configPath string
	mu         sync.RWMutex
	watchers   []func(*Config)
}

// NewConfigManager 创建配置管理器
func NewConfigManager(configPath string) (*ConfigManager, error) {
	cm := &ConfigManager{
		configPath: configPath,
		viper:      viper.New(),
		watchers:   make([]func(*Config), 0),
	}

	if err := cm.loadConfig(); err != nil {
		return nil, fmt.Errorf("加载配置失败: %w", err)
	}

	// 启动配置文件监听
	cm.watchConfig()

	return cm, nil
}

// loadConfig 加载配置
func (cm *ConfigManager) loadConfig() error {
	cm.mu.Lock()
	defer cm.mu.Unlock()

	// 设置配置文件路径
	if cm.configPath == "" {
		cm.configPath = "./config"
	}

	// 设置环境变量支持
	cm.viper.SetEnvPrefix("APP")
	cm.viper.AutomaticEnv()
	cm.viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

	// 设置默认值
	setDefaults(cm.viper)

	// 支持的配置文件列表（按优先级顺序）
	configFiles := []string{
		"base",       // 基础配置
		"middleware", // 中间件配置
		"cache",      // 缓存配置
		"accesslog",  // 访问日志配置
		"config",     // 主配置文件（向后兼容）
	}

	// 逐个加载配置文件
	hasConfigFile := false
	for _, configName := range configFiles {
		// 创建新的viper实例来加载每个配置文件
		v := viper.New()
		v.SetConfigName(configName)
		v.SetConfigType("yaml")
		v.AddConfigPath(cm.configPath)

		if err := v.ReadInConfig(); err != nil {
			if _, ok := err.(viper.ConfigFileNotFoundError); ok {
				// 如果是基础配置文件不存在，且主配置文件也不存在，则使用默认配置
				if configName == "config" && !hasConfigFile {
					fmt.Printf("警告: 未找到配置文件 %s.yaml，使用默认配置\n", configName)
				}
				continue // 配置文件不存在，跳过
			} else {
				return fmt.Errorf("读取配置文件 %s.yaml 失败: %w", configName, err)
			}
		}

		hasConfigFile = true
		fmt.Printf("已加载配置文件: %s.yaml\n", configName)

		// 将读取的配置合并到主viper实例
		if err := cm.viper.MergeConfigMap(v.AllSettings()); err != nil {
			return fmt.Errorf("合并配置文件 %s.yaml 失败: %w", configName, err)
		}
	}

	if !hasConfigFile {
		fmt.Println("警告: 未找到任何配置文件，使用默认配置")
	}

	// 解析配置到结构体
	config := &Config{}
	if err := cm.viper.Unmarshal(config); err != nil {
		return fmt.Errorf("解析配置失败: %w", err)
	}

	// 验证配置
	if err := validateConfig(config); err != nil {
		return fmt.Errorf("配置验证失败: %w", err)
	}

	cm.config = config
	return nil
}

// watchConfig 监听配置文件变化
func (cm *ConfigManager) watchConfig() {
	// 创建文件系统监听器
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		fmt.Printf("创建配置文件监听器失败: %v\n", err)
		return
	}

	// 监听配置目录
	configDir := cm.configPath
	if configDir == "" {
		configDir = "./config"
	}

	err = watcher.Add(configDir)
	if err != nil {
		fmt.Printf("添加配置目录监听失败: %v\n", err)
		watcher.Close()
		return
	}

	// 启动监听协程
	go func() {
		defer watcher.Close()

		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}

				// 检查是否是我们关心的配置文件
				filename := filepath.Base(event.Name)
				isConfigFile := false
				configFiles := []string{
					"base.yaml", "middleware.yaml",
					"cache.yaml", "eventbus.yaml", "config.yaml",
				}

				for _, configFile := range configFiles {
					if filename == configFile {
						isConfigFile = true
						break
					}
				}

				// 只处理配置文件的写入和重命名事件
				if isConfigFile && (event.Op&fsnotify.Write == fsnotify.Write ||
					event.Op&fsnotify.Rename == fsnotify.Rename) {
					fmt.Printf("配置文件发生变化: %s (操作: %s)\n",
						event.Name, event.Op.String())

					// 延迟一下再重新加载，避免文件正在写入时读取
					time.Sleep(100 * time.Millisecond)

					if err := cm.loadConfig(); err != nil {
						fmt.Printf("重新加载配置失败: %v\n", err)
						continue
					}

					// 触发配置变化回调
					cm.notifyWatchers()
				}

			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}
				fmt.Printf("配置文件监听错误: %v\n", err)
			}
		}
	}()
}

// notifyWatchers 通知所有监听器
func (cm *ConfigManager) notifyWatchers() {
	cm.mu.RLock()
	watchers := make([]func(*Config), len(cm.watchers))
	copy(watchers, cm.watchers)
	config := cm.config
	cm.mu.RUnlock()

	for _, watcher := range watchers {
		go watcher(config)
	}
}

// GetConfig 获取配置
func (cm *ConfigManager) GetConfig() *Config {
	cm.mu.RLock()
	defer cm.mu.RUnlock()
	return cm.config
}

// OnConfigChange 注册配置变化监听器
func (cm *ConfigManager) OnConfigChange(watcher func(*Config)) {
	cm.mu.Lock()
	defer cm.mu.Unlock()
	cm.watchers = append(cm.watchers, watcher)
}

// GetString 获取字符串配置
func (cm *ConfigManager) GetString(key string) string {
	return cm.viper.GetString(key)
}

// GetInt 获取整数配置
func (cm *ConfigManager) GetInt(key string) int {
	return cm.viper.GetInt(key)
}

// GetBool 获取布尔配置
func (cm *ConfigManager) GetBool(key string) bool {
	return cm.viper.GetBool(key)
}

// GetDuration 获取时间配置
func (cm *ConfigManager) GetDuration(key string) time.Duration {
	return cm.viper.GetDuration(key)
}

// validateConfig 验证配置
func validateConfig(config *Config) error {
	if config.App.Name == "" {
		return fmt.Errorf("应用名称不能为空")
	}

	if config.Server.Port <= 0 || config.Server.Port > 65535 {
		return fmt.Errorf("服务器端口必须在1-65535之间")
	}

	// JWT配置现在从中间件配置中读取
	if config.Middleware.Auth.JWTSecret == "" || config.Middleware.Auth.JWTSecret == "your-secret-key" {
		return fmt.Errorf("JWT签名密钥不能为空或使用默认值")
	}

	return nil
}
